#include <p18cxxx.h>
#include <timers.h>
#include <sw_spi.h>
#include <spi.h>


#pragma code

/**@brief LED OUTPUT function
This function turns the input led_input_range (must be 16 bit), into a 16 bit led display, then self terminates
and resets all changed registers back to their original state
@author Ben Stewart
@param led_input_range Any 16 bit number
@return void **/
void led_output_16 (unsigned int led_input_range)
{
/** variables block **/
unsigned char led_output_high = 0;
unsigned char led_output_low = 0;
unsigned char counter = 10;
unsigned char store_TRISA = 0;
unsigned char store_TRISB = 0;
unsigned char store_TRISC = 0;
unsigned char store_TRISD = 0;


/** Seperate out the high and low bytes of the input and store in seperate locations **/
	led_output_high = (led_input_range>>8);
	led_output_low	= (led_input_range & 0x00FF);

/** Store the states of the TRIS registers **/
	store_TRISA = TRISA;
	store_TRISB = TRISB;
	store_TRISC = TRISC;
	store_TRISD = TRISD;

	//Settings for SPI mode Master 
	TRISA &= 0b11011111;
//	TRISB &= 0b11011110;
	TRISC |= 0b00010000;
	TRISC &= 0b11010110;

	//Set pin4 and pin5 of portd to be outputs for enable control of shift registers 74HC164's
	TRISD &= 0b11001111;

	//Set up SPI
	SSPCON1bits.CKP = 0;    //settup edge trigger and
	SSPSTATbits.CKE = 1;	//clock normally low
	SSPSTATbits.BF = 0;		//clear the buffer full flag
	SSPSTATbits.SMP = 0;	//sample in the middle of time
	SSPCON1bits.SSPEN = 1;	//enable the SPI
	SSPCON1 &= 0xF0;		//ensure no other settings changed by clearing bottom nibble



	//output zero to SSPBUF to ensure it's clear, then enable the low register and send out the low byte
	SSPBUF = led_output_low;
	PORTD |= 0b00100000;
	SSPBUF = led_output_low;

	//short delay to ensure number has been completely sent
	while(counter>0)
	{
	counter--;
	}
	counter = 1000;


	//turn off the enable pin of the low register
	if(SSPSTATbits.BF ==1)
	{
	PORTD &= 0b11011111;
	}

	//turn on the enable pin for the high register and send the high byte to it
	PORTD |= 0b00010000;		  
	SSPBUF = led_output_high;

	//short delay to ensure the number has been completely sent
	while(counter>0)
	{
	counter--;
	}
	counter = 1000;

	if(SSPSTATbits.BF ==1)
	{
	PORTD &= 0b11101111;

	}


	//Restore the TRIS register values
	TRISA = store_TRISA;
	TRISB = store_TRISB;
	TRISC = store_TRISC;
	TRISD = store_TRISD;



}